package com.cl.optionalbean.tools;

import java.util.HashMap;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @Author Chill_Lyn
 * @Date 2021/3/7 21:30
 */
public final class OptionalBean<T> {
    private static final OptionalBean<?> EMPTY=new OptionalBean<>();
    private final T value;

    private OptionalBean(){
        this.value=null;
    }

    /**
     * 空值抛出空指针
     * @param value
     */
    private OptionalBean(T value) {
        this.value= Objects.requireNonNull(value);
    }

    /**
     * 包装一个不能为空的bean
     * @param value
     * @param <T>
     * @return
     */
    public static <T> OptionalBean<T> of(T value){
        return new OptionalBean<>(value);
    }

    /**
     * 包装一个可以为空的bean
     * @param value
     * @param <T>
     * @return
     */
    public static <T> OptionalBean<T> ofNullable(T value){
        return Objects.isNull(value)?empty():of(value);
    }

    /**
     * 获取具体的值
     * @return
     */
    public T get(){
        return Objects.isNull(value)?null:value;
    }

    /**
     * 如果为空，获取其他值
     * @param other
     * @return
     */
    public T orElse(T other){
        return Objects.isNull(value)?other:value;
    }

    /**
     * 如果为空 通过lambda获取一个值
     * @param other
     * @return
     */
    public T orElseGet(Supplier<? extends T> other){
        return Objects.isNull(value)?other.get():value;
    }

    /**
     * 如果为空，抛出一个指定异常
     * @param exceptionSupplier
     * @param <X>
     * @return
     * @throws X
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X{
        if (Objects.isNull(value)){
            throw exceptionSupplier.get();
        }
        return value;
    }

    /**
     * 是否存在
     * @return
     */
    public boolean isPresent(){
        return !Objects.isNull(value);
    }

    /**
     * 如果不为空，供一个消费者消费
     * @param consumer
     */
    public void ifPresent(Consumer<? super T> consumer){
        if(!Objects.isNull(value)){
            consumer.accept(value);
        }
    }

    /**
     * 空值常量
     * @param <T>
     * @return
     */
    public static <T> OptionalBean<T> empty(){
        return (OptionalBean<T>) EMPTY;
    }

    /**
     * 取出一个可能为空的对象
     * @param function
     * @param <R>
     * @return
     */
    public <R> OptionalBean<R> getBean(Function<? super T,? extends R> function){
        return Objects.isNull(value)?OptionalBean.empty():OptionalBean.ofNullable(function.apply(value));
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
}
